package com.ruoyi.system.schedule;

import com.ruoyi.system.domain.GwContract;
import com.ruoyi.system.service.IGwContractService;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
public class ScheduledTaskServiceImpl implements ScheduledTaskService {

    @Resource
    IGwContractService gwContractService;

    private static final int POOL_SIZE = 500;

    private List<ScheduleTask> tasks = new ArrayList<>();

    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();

    public ScheduledTaskServiceImpl() {
        taskScheduler.setPoolSize(POOL_SIZE);
        taskScheduler.initialize();
    }

    public ScheduleTask initTasks(TimingTask timingTask) {
        ScheduleTask scheduleTask = buildScheduleTask(timingTask);
        List<ScheduleTask> sts = tasks.stream().filter(st -> st.getOrderId().equals(scheduleTask.getOrderId())).collect(Collectors.toList());
        if (ObjectUtils.isEmpty(sts)) {
            tasks.add(scheduleTask);
            return scheduleTask;
        }
        return null;
    }

    private ScheduleTask buildScheduleTask(TimingTask timingTask) {
        ScheduleTask scheduleTask = new ScheduleTask() {
            @Override
            public Runnable doTask() {
                return new Runnable() {
                    @SneakyThrows
                    @Override
                    public void run() {
                        try {
                            //删除超时未发起的合同
                            GwContract gwContract = gwContractService.selectGwContractById(timingTask.getOrderId());
                            if(ObjectUtils.isNotEmpty(gwContract) && "PREPARE".equals(gwContract.getStatus())){
                                gwContractService.deleteGwContractById(gwContract.getId() + "");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };
            }

            @Override
            public void start() {
                taskScheduler.schedule(doTask(), startDate());
            }

            @Override
            public void stop() {
                taskScheduler.shutdown();
            }

            @Override
            public Date startDate() {
                return timingTask.getStartDate();
            }

            @Override
            public String getOrderId() {
                return timingTask.getOrderId();
            }

            @Override
            public Boolean tempFlag() {
                return timingTask.getTempFlag();
            }

            @Override
            public TimingTask timingTask() {
                return timingTask;
            }
        };
        return scheduleTask;
    }

    public void start() {
        for (ScheduleTask task : tasks) {
            task.start();
        }
    }

    public void addTask(ScheduleTask task) {
        taskScheduler.initialize();
//        taskScheduler.schedule(task.doTask(), new CronTrigger(task.cron()));
        taskScheduler.schedule(task.doTask(), task.startDate());
    }

    @Override
    public void stopAll() {
        if (taskScheduler != null) {
            taskScheduler.shutdown();
            for (ScheduleTask task : tasks) {
                task.stop();
            }
        }
    }

    @Override
    public void stopTask(List<TimingTask> timingTasks) {
        if (tasks.size() > 0) {
            //不知道为啥最后一个不停 加上
            if (tasks.size() == 1 || taskScheduler.getActiveCount() == 1) {
                initPool();
            }
            //不知道为啥最后一个不停 加上
            for (int i = 0; i < timingTasks.size(); i++) {
                TimingTask timingTask = timingTasks.get(i);
                for (int i1 = 0; i1 < tasks.size(); i1++) {
                    ScheduleTask task = tasks.get(i1);
                    if (task.getOrderId().equalsIgnoreCase(timingTask.getOrderId())) {
                        task.stop();
                        tasks.remove(task);
                    }
                }
            }
        }
    }

    @Override
    public void startTask(List<TimingTask> startTasks) {
        for (int i = 0; i < startTasks.size(); i++) {
            TimingTask timingTask = startTasks.get(i);
            ScheduleTask scheduleTask = this.initTasks(timingTask);
            //重复的订单号只加一次
            if (ObjectUtils.isNotEmpty(scheduleTask)) {
                this.addTask(scheduleTask);
            }
        }
    }

    @Override
    public List<ScheduleTask> getTasks() {
        return tasks;
    }

    public void initPool() {
        this.stopAll();
        taskScheduler.setPoolSize(POOL_SIZE);
        taskScheduler.initialize();
        tasks = new ArrayList<>();
    }

}